package com.younge.spring.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.younge.spring.api.param.RoleListParam;
import com.younge.spring.api.param.RoleUpdateParam;
import com.younge.spring.repository.SysRolePermissionRepository;
import com.younge.spring.repository.SysRoleRepository;
import com.younge.spring.repository.dao.SysRole;
import com.younge.spring.repository.dao.SysRolePermission;
import jakarta.persistence.criteria.Predicate;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Service
public class SysRoleService {

    private final ObjectMapper mapper;
    private final SysRoleRepository sysRoleRepository;
    private final SysRolePermissionRepository sysRolePermissionRepository;

    public SysRoleService(ObjectMapper mapper, SysRoleRepository sysRoleRepository,
                          SysRolePermissionRepository sysRolePermissionRepository) {
        this.mapper = mapper;
        this.sysRoleRepository = sysRoleRepository;
        this.sysRolePermissionRepository = sysRolePermissionRepository;
    }

    public Page<SysRole> getRoleList(RoleListParam param) {
        Pageable pageable = PageRequest.of(param.getPage() - 1, param.getPageSize());
        Specification<SysRole> spec = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();

            Long id = param.getId();
            if (null != id) {
                predicates.add(cb.equal(root.get("id"), id));
            }
            String name = StringUtils.trimAllWhitespace(param.getName());
            if (StringUtils.hasText(name)) {
                predicates.add(cb.equal(root.get("name"), name));
            }
            Integer status = param.getStatus();
            if (null != status) {
                predicates.add(cb.equal(root.get("status"), status));
            }

            String remark = StringUtils.trimAllWhitespace(param.getRemark());
            if (StringUtils.hasText(remark)) {
                predicates.add(cb.like(root.get("remark"), remark + "%"));
            }

            LocalDate startTime = param.getStartTime();
            LocalDate endTime = param.getEndTime();
            if (null != startTime) {
                predicates.add(cb.greaterThanOrEqualTo(root.get("createTime"), startTime));
            }
            if (null != endTime) {
                predicates.add(cb.lessThan(root.get("createTime"), endTime.plusDays(1)));
            }

            return cb.and(predicates.toArray(new Predicate[0]));
        };
        return sysRoleRepository.findAll(spec, pageable).map(sysRole -> {
            Long roleId = sysRole.getId();
            return sysRole;
        });
    }

    public boolean isRoleNameExists(Long id, String name) {
        //return SysRoleRepository.findByName(name).map(sysRole -> !sysRole.getId().equals(id)).orElse(false);
        return true;
    }

    @Transactional
    public String updateRole(RoleUpdateParam param) {
        SysRole sysRole = sysRoleRepository.findById(param.getId()).orElseThrow(() -> new RuntimeException("角色不存在！"));

        sysRole.setStatus(param.getStatus());
        String name = param.getName();
        String remark = param.getRemark();
        if (StringUtils.hasText(name)) {
            sysRole.setName(name);

            sysRole.setRemark(remark);

            sysRolePermissionRepository.deleteAllByRoleId(param.getId());
            Set<Long> ids = param.getPermissions();
            if (!ids.isEmpty()) {
                List<SysRolePermission> sysRolePermissions = ids.stream().map(r -> {
                    SysRolePermission p = new SysRolePermission();
                    p.setPermissionId(r);
                    p.setRoleId(param.getId());
                    return p;
                }).toList();
                sysRolePermissionRepository.saveAll(sysRolePermissions);
            }
        }

        sysRoleRepository.save(sysRole);
        return "保存成功！";
    }

    public String createRole(SysRole param) {
        sysRoleRepository.save(param);
        return "角色创建成功";
    }

    public Set<Long> getRolePermissions(Long id) {
        return sysRolePermissionRepository.findPermissionByRoleId(id);
    }
}